package com.sxbbc.api.service.impl;

import java.io.InputStream;

import com.sxbbc.common.basics.service.redis.RedisUtilsService;
import com.sxbbc.common.core.service.system.mode.ModeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.api.service.IRegisterService;
import com.sxbbc.common.basics.emails.SendMail;
import com.sxbbc.common.basics.enums.LoginChannelEnums;
import com.sxbbc.common.basics.enums.RandNumType;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.files.RestUploadFileInfo;
import com.sxbbc.common.basics.files.UploadUtils;
import com.sxbbc.common.basics.login.LoginDto;
import com.sxbbc.common.basics.login.ThirdLoginDto;
import com.sxbbc.common.basics.sms.SendSms;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.basics.utils.date.DateUtil;
import com.sxbbc.common.basics.utils.encrypts.des.DESEncode;
import com.sxbbc.common.basics.utils.encrypts.pwd.Encode;
import com.sxbbc.common.basics.utils.qr.QRCodeUtil;
import com.sxbbc.common.basics.utils.radoms.RandNumUtils;
import com.sxbbc.common.basics.utils.regular.RpxUtils;
import com.sxbbc.common.basics.utils.statics.FunctionUtils;
import com.sxbbc.common.basics.utils.statics.StaticUtils;
import com.sxbbc.common.basics.wx.client.WxClient;
import com.sxbbc.common.core.dto.jz.LoginRegisterVo;
import com.sxbbc.common.core.dto.jz.WxBindVo;
import com.sxbbc.common.core.entity.jz.CAccount;
import com.sxbbc.common.core.entity.jz.CCustomer;
import com.sxbbc.common.core.entity.jz.CTempWx;
import com.sxbbc.common.core.service.ICAccountService;
import com.sxbbc.common.core.service.ICConfigurationService;
import com.sxbbc.common.core.service.ICCustomerService;
import com.sxbbc.common.core.service.ICTempWxService;
import com.sxbbc.common.core.service.IInfoParamService;
import com.sxbbc.common.core.service.system.login.LoginTokenService;
import com.sxbbc.common.core.utils.MsgUtils;

/**
 * 会员注册
 *
 * @author YQQ
 */
@Service
public class RegisterServiceImpl implements IRegisterService {

    @Autowired
    private ICCustomerService customerService;
    @Autowired
    private ICAccountService cAccountService;
    @Autowired
    private ICTempWxService cTempWxService;
    @Autowired
    private LoginTokenService loginTokenService;
    @Autowired
    private IInfoParamService infoParamService;
    @Autowired
    private ICConfigurationService icConfigurationService;
    @Autowired
    private ModeService modeService;
    @Autowired
    private RedisUtilsService redisUtilsService;

    /**
     * 发送注册验证码
     *
     * @param loginRegisterVo type 1手机号 2邮箱
     *                        phone 手机号
     *                        email 邮箱
     * @return
     */
    @Override
    public RestResponse sendRegisterCode(LoginRegisterVo loginRegisterVo) {
        if (loginRegisterVo.getType() == null) {
            return GetRest.getFail("请选择注册类型");
        }
        CCustomer customer = new CCustomer();
        RestResponse restResponse = null;
        //手机号注册
        if (CalcuUtils.getInstance().isEquals(loginRegisterVo.getType(), StaticUtils.PHONE_LOGIN)) {
            //校验用户信息
            customer.setRegisterType(StaticUtils.PHONE_LOGIN);
            customer.setPhone(loginRegisterVo.getLogin());
            customer = customerService.getCustomer(customer);
            if (customer != null) {
                return GetRest.getFail("该手机号已注册");
            }
            //发送验证码到手机号
            restResponse = SendSms.getInstance().sendSmsAliyun(loginRegisterVo.getLogin(), MsgUtils.ALI_SMS_REGISTER);
            //邮箱注册
        } else if (CalcuUtils.getInstance().isEquals(loginRegisterVo.getType(), StaticUtils.EMAIL_LOGIN)) {
            //校验用户信息
            customer.setRegisterType(StaticUtils.EMAIL_LOGIN);
            customer.setEmail(loginRegisterVo.getLogin());
            customer = customerService.getCustomer(customer);
            if (customer != null) {
                return GetRest.getFail("该邮箱已注册");
            }
            //发送验证码到邮箱
            restResponse = SendMail.getInstance().sendValid(loginRegisterVo.getLogin());
        }
        //发送验证码
        return restResponse;
    }

    /**
     * 注册
     * <p>
     * 参数详见 {@link LoginRegisterVo} 注释
     *
     * @param client
     * @return
     */
    @Override
    public RestResponse handleRegister(LoginRegisterVo loginRegisterVo, WxClient client) {
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (loginRegisterVo.getType() == null) {
            return GetRest.getFail("注册类型不能为空");
        }
        if (loginRegisterVo.getProId() == null || loginRegisterVo.getCityId() == null || loginRegisterVo.getAreaId() == null) {
            return GetRest.getFail("所选地区不能为空");
        }
        if (StringUtils.isBlank(loginRegisterVo.getLogin())) {
            return GetRest.getFail("账号不能为空");
        }
        if (StringUtils.isBlank(loginRegisterVo.getPassword())) {
            return GetRest.getFail("请输入密码");
        }

        if (StringUtils.isBlank(loginRegisterVo.getImgCode())) {
            return GetRest.getFail("请输入图形验证码");
        }
        //保存对象
        CCustomer customer = new CCustomer();
        //查询对象
        CCustomer cCustomer = new CCustomer();
        //昵称
        String nickname = "";
        RestResponse restResponse = null;

        //不同账号方式注册
        if (calcuUtils.isEquals(loginRegisterVo.getType(), StaticUtils.PHONE_LOGIN)) {
            //验证手机号是否注册
            cCustomer.setRegisterType(StaticUtils.PHONE_LOGIN);
            cCustomer.setPhone(loginRegisterVo.getLogin());
            cCustomer = customerService.getCustomer(cCustomer);
            if (cCustomer != null) {
                return GetRest.getFail("该手机号已注册！");
            }

            //验证图形验证码,-1表示网页传来的图形验证码，网页不加图形验证码，以此跳过验证
            if (!loginRegisterVo.getImgCode().equals("-1")) {
                String validcode = redisUtilsService.getKey("validcode_" + loginRegisterVo.getLogin());
                if (!StringUtils.equalsIgnoreCase(validcode, loginRegisterVo.getImgCode())) {
                    return GetRest.getFail("图形验证码不正确");
                }
            }

            //校验手机号验证码
            restResponse = SendSms.getInstance().validSms(loginRegisterVo.getLogin(), loginRegisterVo.getValidCode());
            customer.setPhone(loginRegisterVo.getLogin());
            nickname = FunctionUtils.replay(loginRegisterVo.getLogin());
        } else if (calcuUtils.isEquals(loginRegisterVo.getType(), StaticUtils.EMAIL_LOGIN)) {
            //验证邮箱是否注册
            cCustomer.setRegisterType(StaticUtils.EMAIL_LOGIN);
            cCustomer.setEmail(loginRegisterVo.getLogin());
            cCustomer = customerService.getCustomer(cCustomer);
            if (cCustomer != null) {
                return GetRest.getFail("该邮箱已注册！");
            }
            //校验邮箱验证码
            restResponse = SendMail.getInstance().validEmail(loginRegisterVo.getLogin(), loginRegisterVo.getValidCode());
            customer.setEmail(loginRegisterVo.getLogin());
            nickname = loginRegisterVo.getLogin();
        } else if (calcuUtils.isEquals(loginRegisterVo.getType(), StaticUtils.ACCOUNT_LOGIN)) {
            //验证用户名
            String validLogin = RpxUtils.getInstance().validLogin(loginRegisterVo.getLogin());
            if (!validLogin.equals("")) {
                return GetRest.getFail(validLogin);
            }
            //验证密码
            String validPwd = RpxUtils.getInstance().validPassword(loginRegisterVo.getPassword());
            if (!validPwd.equals("")) {
                return GetRest.getFail(validPwd);
            }
            //验证用户名是否注册
            cCustomer.setRegisterType(StaticUtils.ACCOUNT_LOGIN);
            cCustomer.setLogin(loginRegisterVo.getLogin());
            cCustomer = customerService.getCustomer(cCustomer);
            if (cCustomer != null) {
                return GetRest.getFail("该账号已注册！");
            }
            customer.setLogin(loginRegisterVo.getLogin());
            nickname = loginRegisterVo.getLogin();
        } else {
            return GetRest.getFail("注册类型错误");
        }
        //校验手机验证码或邮箱状态
        if (restResponse != null && !restResponse.isStatus()) {
            return restResponse;
        }

        if (client != null && !StringUtils.isBlank(client.getUnionid())) {
            customer.setNickName(client.getNickname());
            customer.setHeadurl(client.getHeadimgurl());
            customer.setUnionid(client.getUnionid());
            customer.setRegisterChannel(LoginChannelEnums.WX.getChannel());
        } else {
            customer.setNickName(nickname);
            customer.setRegisterChannel(loginRegisterVo.getChannel());
        }
        //密码加密
        String password = Encode.md5Encode(loginRegisterVo.getPassword());
        customer.setPassWord(password);
        // 个人邀请码
        String code = "code";
        do {
            code = Encode.getRandomNum(8, 2);
        } while (customerService.getByInviteCode(code) != null);
        customer.setInviteCode(code);

        //推荐人处理
        Integer parentId = null;
        if (StringUtils.isNotBlank(loginRegisterVo.getInviteCode())) {
            CCustomer parent = customerService.getByInviteCode(loginRegisterVo.getInviteCode());
            if (parent == null) {
                return GetRest.getFail("推荐人不存在");
            }
            parentId = parent.getId();
            customer.setParentid(parent.getId());
            customer.setLayer(parent.getLayer() + 1);
            if (StringUtils.isEmpty(parent.getGenes())) {
                customer.setGenes(parent.getId() + "");
            } else {
                customer.setGenes(parent.getGenes() + "," + parent.getId());
            }
        }

        //创建用户
        customer.setProId(loginRegisterVo.getProId());
        customer.setCityId(loginRegisterVo.getCityId());
        customer.setAreaId(loginRegisterVo.getAreaId());
        boolean result = customerService.save(customer);
        if (!result) {
            return GetRest.getFail("注册失败");
        }
        Integer cid = customer.getId();

        //XXX 临时解决多端验证码，三联推荐码生成体验极差，等待高手优化
        //APP个人推荐码
        InputStream is = QRCodeUtil.getInstance().encode("http://h5.danongkj.cn/jzz/#/pages/Tabbar/User/index?inviteCode=" + code + "&parentPhone=" + loginRegisterVo.getLogin());
        String filename = DateUtil.getInstance().currentTimeMillis() + RandNumUtils.getInstance().get(RandNumType.NUMBER, 5) + "." + QRCodeUtil.getInstance().FORMAT_NAME;
        RestUploadFileInfo r = UploadUtils.getInstance().uploadFile(is, filename);
        customer.setQrApp(r.getData());
        //公众个人推荐码
        is = QRCodeUtil.getInstance().encode("http://h5.danongkj.cn/jzz/#/pages/Tabbar/User/index?inviteCode=" + code + "&parentPhone=" + loginRegisterVo.getLogin());
        filename = DateUtil.getInstance().currentTimeMillis() + RandNumUtils.getInstance().get(RandNumType.NUMBER, 5) + "." + QRCodeUtil.getInstance().FORMAT_NAME;
        r = UploadUtils.getInstance().uploadFile(is, filename);
        if (r.isStatus()) {
            customer.setQrWx(r.getData());
        }
        //小程序个人推荐码
//        is = QRCodeUtil.getInstance().encode("http://h5.danongkj.cn/share/program?inviteCode=" + code);
//        filename = DateUtil.getInstance().currentTimeMillis() + RandNumUtils.getInstance().get(RandNumType.NUMBER, 5) + "." + QRCodeUtil.getInstance().FORMAT_NAME;
//        r = UploadUtils.getInstance().uploadFile(is, filename);
//        if (r.isStatus()) {
//            customer.setQrProgram(r.getData());
//        }

        //XXX 该步骤不知道干什么，根本没法进入
        if (client != null && !StringUtils.isBlank(client.getUnionid())) {
            //如果是微信
            // 修改用户微信推广二维码
            is = QRCodeUtil.getInstance().encode("");
            filename = DateUtil.getInstance().currentTimeMillis() + RandNumUtils.getInstance().get(RandNumType.NUMBER, 5) + "." + QRCodeUtil.getInstance().FORMAT_NAME;
            r = UploadUtils.getInstance().uploadFile(is, filename);
            customer.setQrWx(r.getData());
        }

        customerService.updateById(customer);
        CAccount account = new CAccount();
        account.setCid(cid);
        result = cAccountService.save(account);
        if (!result) {
            throw new ThrowJsonException("注册失败");
        }
        String getCid = DESEncode.getInstance().encrypt(cid + "_token+sxbbc");
        return GetRest.getSuccess("注册成功", getCid);

    }

    @Override
    public RestResponse handleWxUserBind(WxBindVo bindVo) {
        // 渠道——判断是微信还是小程序
        Integer channel = bindVo.getChannel();
        if (channel == null || StringUtils.isEmpty(bindVo.getOpenId())) {
            return GetRest.getFail("绑定失败");
        }

        // 需要绑定的手机号
        String phone = bindVo.getPhone();
        CCustomer customer = new CCustomer();
        customer.setPhone(phone);
        customer = customerService.getCustomer(customer);

        // 授权获取到的用户信息-临时数据
        CTempWx tempWx = cTempWxService.getByMsg(null, bindVo.getOpenId(), channel);
        if (tempWx == null) {
            return GetRest.getFail("用户信息不存在");
        }
        String share = "";


        // 如果账户不存在是新增还是返回提示
        if (customer == null) {
            LoginRegisterVo loginRegisterVo = new LoginRegisterVo();
            loginRegisterVo.setLogin(phone);
            loginRegisterVo.setType(StaticUtils.PHONE_LOGIN);
            loginRegisterVo.setChannel(channel);
            loginRegisterVo.setValidCode(bindVo.getValidCode());
            loginRegisterVo.setInviteCode(bindVo.getInviteCode());
            loginRegisterVo.setPassword(CalcuUtils.getInstance().getOrderCode("PS"));
            loginRegisterVo.setImgCode("-1");
            loginRegisterVo.setProId(bindVo.getProId());
            loginRegisterVo.setCityId(bindVo.getCityId());
            loginRegisterVo.setAreaId(bindVo.getAreaId());
            RestResponse result = handleRegister(loginRegisterVo, null);
            if (!result.isStatus()) {
                return result;
            }
            share = result.getFlag();
            String token = (String) result.getData();
            String decrypt = DESEncode.getInstance().decrypt(token);
            Integer cid = Integer.parseInt(decrypt.substring(0, decrypt.indexOf("_")));
            customer = customerService.getById(cid);
            if (customer == null) {
                throw new ThrowJsonException("绑定账号异常");
            }
            customer.setNickName(tempWx.getNickName());
            customer.setHeadurl(tempWx.getHeadUrl());
        } else {
            // 如果当前用户不为空——判断用户是否绑定过
            if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.WX.getChannel())) {
                if (StringUtils.isNotBlank(customer.getOpenidWx())) {
                    return GetRest.getFail("当前手机号已绑定其它微信账户");
                }
            } else if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.PROGRAM.getChannel())) {
                if (StringUtils.isNotBlank(customer.getOpenidProgram())) {
                    return GetRest.getFail("当前手机号已绑定其它小程序账户");
                }
            }
        }
        customer.setUnionid(tempWx.getUnionid());
        if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.WX.getChannel())) {
            customer.setOpenidWx(tempWx.getOpenid());
            customer.setRegisterChannel(LoginChannelEnums.WX.getChannel());
            //TODO 生成微信个人二维码，暂时放在注册统一生成
        } else if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.PROGRAM.getChannel())) {
            customer.setOpenidProgram(tempWx.getOpenid());
            customer.setRegisterChannel(LoginChannelEnums.PROGRAM.getChannel());
            //TODO 生成小程序个人二维码，暂时放在注册统一生成

        }
        customer.setProId(bindVo.getProId());
        customer.setCityId(bindVo.getCityId());
        customer.setAreaId(bindVo.getAreaId());
        customer.setLogin(phone);
        boolean result = customerService.updateById(customer);
        if (result) {
            // 保存的临时数据删除
            cTempWxService.removeById(tempWx.getId());
            // 操作登陆——返回token
            LoginDto loginDto = LoginDto.getInstance();
            loginDto.setCid(customer.getId());
            loginDto.setWxopenid(customer.getOpenidWx());
            loginDto.setChannel(channel);
            LoginChannelEnums loginChannelEnums = null;
            // 小程序
            if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.PROGRAM.getChannel())) {
                loginChannelEnums = LoginChannelEnums.PROGRAM;
                loginDto.setProgramopenid(customer.getOpenidProgram());
            } else if (CalcuUtils.getInstance().isEquals(channel, LoginChannelEnums.WX.getChannel())) {
                loginChannelEnums = LoginChannelEnums.WX;
                loginDto.setProgramopenid(customer.getOpenidWx());
            }
            RestResponse loginResult = loginTokenService.getLoginToken(loginDto, loginChannelEnums);
            loginResult.setFlag(share);
            return loginResult;
        }
        return GetRest.getFail("绑定失败");
    }

    @Override
    public RestResponse handleThirdNoAccountBind(ThirdLoginDto thirdLoginDto, LoginRegisterVo registerVo) {
        if (thirdLoginDto == null) {
            return GetRest.getFail("授权用户信息获取失败");
        }
        if (StringUtils.isEmpty(thirdLoginDto.getUid()) || thirdLoginDto.getType() == null) {
            return GetRest.getFail("授权用户信息获取失败");
        }
        registerVo.setChannel(LoginChannelEnums.APP.getChannel());
        registerVo.setType(StaticUtils.PHONE_LOGIN);
        registerVo.setImgCode("-1");
        RestResponse registerResult = handleRegister(registerVo, null);
        if (!registerResult.isStatus()) {
            return registerResult;
        }
        String token = (String) registerResult.getData();
        String decrypt = DESEncode.getInstance().decrypt(token);
        Integer cid = Integer.parseInt(decrypt.substring(0, decrypt.indexOf("_")));
        CCustomer customer = customerService.getById(cid);
        if (customer == null) {
            throw new ThrowJsonException("绑定账号异常");
        }
        customer.setHeadurl(thirdLoginDto.getIconurl());
        int sex = 0;
        if ("男".equals(thirdLoginDto.getGender())) {
            sex = 1;
        } else if ("女".equals(thirdLoginDto.getGender())) {
            sex = 2;
        }
        customer.setSex(sex);
        customer.setLogin(registerVo.getLogin());
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(thirdLoginDto.getType(), StaticUtils.THIRD_QQ)) {
            // 第三方登录——QQ
            customer.setOpenidQq(thirdLoginDto.getUid());
        } else if (calcuUtils.isEquals(thirdLoginDto.getType(), StaticUtils.THIRD_WX)) {
            // 第三方登录——WX
            customer.setUnionid(thirdLoginDto.getUid());
        } else {
            return GetRest.getFail("绑定失败");
        }
        boolean result = customerService.updateById(customer);
        if (result) {
            // 操作登陆——返回token
            LoginDto loginDto = LoginDto.getInstance();
            loginDto.setCid(customer.getId());
            loginDto.setWxopenid(customer.getOpenidWx());
            loginDto.setChannel(LoginChannelEnums.APP.getChannel());
            RestResponse loginResult = loginTokenService.getLoginToken(loginDto, LoginChannelEnums.APP);
            loginResult.setFlag(registerResult.getFlag());
            return loginResult;
        }
        return GetRest.getFail("绑定失败");
    }

    @Override
    public RestResponse handleThirdAccountBind(ThirdLoginDto thirdLoginDto, Integer cid, String phone, String passWord) {
        if (thirdLoginDto == null) {
            return GetRest.getFail("授权用户信息获取失败");
        }
        if (StringUtils.isEmpty(thirdLoginDto.getUid()) || thirdLoginDto.getType() == null) {
            return GetRest.getFail("授权用户信息获取失败");
        }

        CCustomer customer = new CCustomer();
        if (cid != null) {
            customer = customerService.getById(cid);
        } else {
            if (StringUtils.isBlank(phone)) {
                return GetRest.getFail("请输入手机号");
            }
            CCustomer queryCustomer = new CCustomer();
            queryCustomer.setPhone(phone);
            customer = customerService.getCustomer(queryCustomer);
            if (customer == null) {
                return GetRest.getFail("请检查手机号码是否输入正确");
            }
            // 校验密码
            if (StringUtils.isEmpty(passWord)) {
                return GetRest.getFail("请输入密码");
            }
            String encryPayword = Encode.md5Encode(passWord);
            if (!encryPayword.equals(customer.getPayWord())) {
                return GetRest.getFail("密码不正确");
            }
        }

        // 校验通过
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(thirdLoginDto.getType(), StaticUtils.THIRD_QQ)) {
            // 第三方登录——QQ
            customer.setOpenidQq(thirdLoginDto.getUid());
        } else if (calcuUtils.isEquals(thirdLoginDto.getType(), StaticUtils.THIRD_WX)) {
            // 第三方登录——WX
            customer.setUnionid(thirdLoginDto.getUid());
        } else {
            return GetRest.getFail("绑定失败");
        }
        boolean result = customerService.updateById(customer);
        if (result) {
            // 操作登陆——返回token
            LoginDto loginDto = LoginDto.getInstance();
            loginDto.setCid(customer.getId());
            loginDto.setWxopenid(customer.getOpenidWx());
            loginDto.setChannel(LoginChannelEnums.APP.getChannel());
            return loginTokenService.getLoginToken(loginDto, LoginChannelEnums.APP);
        }
        return GetRest.getFail("绑定失败");
    }
}
